package com.mantru.iotpot.modbus;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.text.*;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import com.mantru.iotpot.ApplicationClass;

public class RobotClientEventThread extends Thread
{
    public boolean Active;     //线程状态
    private ApplicationClass ac;
    private List list;         //放自身的消息队列
    private String ServerIP, ServerPort;
    private String EventMemo;
    private boolean SocketStatus;  //true表示连接成功，false表示已断开
    private Socket ClientSocket;
    private OutputStream OutStream;
    private InputStream InStream;
    private RobotClientReadThread CRT;
    private long LastConnectTime, LastActiveTime;
    private String HttpResponseJson = "";
    private String icbc_server_url = "https://gdfhyxh.dccnet.com.cn/senddata.aspx";

    //常量
    private byte BUFFER_TYPE_SUBMIT = 2;           //下行包，即将要发给客户端的包
    private byte BUFFER_TYPE_QUIT = 4;             //终止线程
    private byte BUFFER_TYPE_ICBC = 5;             //给工行服务器发指令
    private byte COMMAND_SOCKET_CLOSE = 127;              //关闭socket连接
    private String DEVICE_ID = "";
    private String LastMenuID = "";
    private String LastMenuName = "";
    private String LastIcbcIP = "";
    private String LastIcbcPort = "";
    private String LastDeviceID = "";
    private Handler UIHandle;


    //构造函数
    public RobotClientEventThread(ApplicationClass aAC, String aDeviceID)
    {
        ac = aAC;
        list = new ArrayList();
        Active = true;
        ServerIP = "120.79.143.198";
        ServerPort = "8001";
        DEVICE_ID = aDeviceID;
        SocketStatus = false;
        LastConnectTime = 0;
        LastActiveTime = 0;
        EventMemo = "";
        UIHandle = null;
        Log("RobotClientEventThread create success");
    }


    @Override
    public void run()
    {
        ObjectBuffer obj;
        while (Active)
        {
            try
            {
                if (SocketStatus == false)
                {
                    long aNowTime = GetTickes();
                    if (aNowTime - LastConnectTime >= 3 * 1000)   //3秒重连
                        ConnectToServer();
                }

                obj = (ObjectBuffer)GetObject();
                if (obj != null)
                {
                    //处理终止线程命令
                    if (obj.Type == BUFFER_TYPE_QUIT)
                    {
                        UIHandle = null;
                        DisconnectSocket();
                        Active = false;
                        break;
                    }
                    //发送信令给客户端
                    if (obj.Type == BUFFER_TYPE_SUBMIT)
                    {
                        BUFFER_TYPE_SUBMIT(obj);
                    }
                    obj.Dispose();
                    obj = null;
                }
                BUFFER_TYPE_TIMER_ACTIVE();
                Thread.sleep(200);
                if (ac.app_is_release == true) {
                    Active = false;
                    CRT.Abort();
                }
            }
            catch (Exception E)
            {
                Active = false;
                Log("RobotClientEventThread RUN出错，错误内容：" + E.getMessage());
            }
        }

        Log("RobotClientEventThread end run");
    }

    private void Log(String value)
    {
        Date nowDate = new Date();
        SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String log_str = "[" + format.format(nowDate) + "] socket-->" + value;

        System.out.println(log_str);
    }

    //向线程增加命令字
    public void AddSubmitData(String json_data)
    {
        ObjectBuffer obj = new ObjectBuffer(BUFFER_TYPE_SUBMIT);
        obj.BodyString = json_data;
        AddObject(obj);
    }

    //向线程增加命令字
    public void AddObject(Object obj)
    {
        synchronized(list)
        {
            list.add(obj);
        }
    }

    //在线程命令字队列前插入命令字
    public void InsertObject(Object obj)
    {
        synchronized(list)
        {
            list.add(0, obj);
        }
    }

    public int GetObjectCount()
    {
        return list.size();
    }

    private Object GetObject()
    {
        if (list.size() > 0)
        {
            Object obj;
            synchronized(list)
            {
                obj = list.get(0);
                list.remove(obj);
            }
            return obj;
        }
        return null;
    }

    //关闭线程
    public void Abort()
    {
        UIHandle = null;
        ObjectBuffer ob = new ObjectBuffer(BUFFER_TYPE_QUIT);
        InsertObject(ob);
    }

    public void ReceiveCallBack(byte[] aReceiveBuffer)
    {
        if (Active == false)
            return;
        boolean Error = false;
        try
        {
            byte[] bytes = PeekBytesValue(aReceiveBuffer, 0, aReceiveBuffer.length);
            int REnd = bytes.length;
            if (REnd > 0)
            {
                LastActiveTime = GetTickes();
                if (REnd > 4)
                {
                    String json_data = PeekStringValue(bytes, 4, bytes.length - 4);
                    Log("RobotClient收到" + REnd + "长度的数据：" + json_data);

                    String cmd = Common.JSON_GetFieldValue(json_data, "cmd");
                    if (cmd.equals("synchronization"))
                    {
                        //发消息给前端UI执行同步菜谱
                        SendMessageToUI(json_data);
                    }

                    Log("RobotClient收到：" + json_data);
                }
            }
            else
            {
                Error = true;
            }
        }
        catch (Exception E)
        {
            Log("RobotClientEventThread接收数据包出错，错误内容：" + E.getMessage());
            Error = true;
        }
        if (Error)
            SocketErrorEvent();
    }

    //向客户端发送数据包
    private void BUFFER_TYPE_SUBMIT(ObjectBuffer obj)
    {
        if (obj.Command_Id == COMMAND_SOCKET_CLOSE)
        {
            try
            {
                Log("RobotClient收到主动断socket命令");
                DisconnectSocket();
                System.gc();
            }
            catch(Exception e1)
            {}
            return;
        }
        boolean Error = false;
        byte[] bytes = new byte[0];
        if (obj.BodyString != null && obj.BodyString.length() > 0)
        {
            bytes = GetCommanBuffer(obj.BodyString);
        }
        try
        {
            if (Error == false && bytes.length > 0)
            {
                String hex = DATA_10TO16(bytes);
                Log("RobotClient发送数据包：" + hex);
                OutStream.write(bytes);
                OutStream.flush();
                LastActiveTime = GetTickes();
            }
        }
        catch (Exception E)
        {
            Log("RobotClientEventThread 发送数据包出错，错误内容：" + E.getMessage());
            Error = true;

        }
        bytes = null;
        if (Error)
        {
            SocketErrorEvent();
        }
    }


    //清扫沉默用户
    private void BUFFER_TYPE_TIMER_ACTIVE()
    {
        try
        {
            long nowTime = GetTickes();
            if (SocketStatus == true && nowTime - LastActiveTime >= 10 * 1000)
            {
                //Log("RobotClient发送一次心跳");
                ObjectBuffer ob = new ObjectBuffer(BUFFER_TYPE_SUBMIT);
                ob.BodyString = "{\"cmd\":\"Timer\"}";
                AddObject(ob);
            }
        }
        catch(Exception E)
        { }
    }

    //连接服务器
    private void ConnectToServer()
    {
        if (SocketStatus)
            return;
        if (ClientSocket != null)
        {
            try
            {
                ClientSocket.close();
                ClientSocket = null;
                SocketStatus = false;
            }
            catch(Exception e)
            {
                SocketStatus = false;
            }
        }
        if (CRT != null)
        {
            CRT.Abort();
            CRT = null;
        }
        try
        {
            ac.net_work_status = 0;
            Log("Robot ConnectToServer[" + ServerIP + ":" + ServerPort + "] begin");
            LastConnectTime = GetTickes();
            ClientSocket = new Socket();
            SocketAddress SA = new InetSocketAddress(ServerIP, Integer.parseInt(ServerPort));
            ClientSocket.connect(SA, 5000);
            OutStream = ClientSocket.getOutputStream();
            InStream = ClientSocket.getInputStream();
            CRT = new RobotClientReadThread(InStream, this);
            CRT.start();
            SocketStatus = true;
            ac.net_work_status = 1;

            SendStatusToUI();
            ObjectBuffer ob = new ObjectBuffer(BUFFER_TYPE_SUBMIT);
            ob.BodyString = "{\"cmd\":\"Login\",\"device_id\":\""+DEVICE_ID+"\"}";
            AddObject(ob);
        }
        catch(Exception e)
        {
            Log("Robot ConnectToServer Error:" + e.getMessage());
            LastConnectTime = GetTickes();
            SocketStatus = false;
            ClientSocket = null;
            CRT = null;
            SendStatusToUI();
        }
    }

    private void DisconnectSocket()
    {
        SocketStatus = false;
        try
        {
            if (CRT != null)
            {
                CRT.Abort();
                CRT = null;
            }
        }
        catch(Exception E)
        { }
        try
        {
            if (ClientSocket != null)
            {
                ClientSocket.shutdownInput();
            }
        }
        catch(Exception E)
        { }
        try
        {
            if (ClientSocket != null)
            {
                ClientSocket.shutdownOutput();
            }
        }
        catch(Exception E)
        { }
        try
        {
            if (ClientSocket != null)
            {
                ClientSocket.close();
            }
        }
        catch(Exception E)
        { }
        ClientSocket = null;
        CRT = null;
        LastConnectTime = GetTickes();
    }

    private void SocketErrorEvent()
    {
        ObjectBuffer obj = new ObjectBuffer(BUFFER_TYPE_SUBMIT);
        obj.Command_Id = COMMAND_SOCKET_CLOSE;
        obj.BodyString = "";
        AddObject(obj);
    }

    private String PROCESS_RECEIVE_DATA(String aPackData)
    {
        //Log("开始处理PackData=" + aPackData);
        String aReturnData = "";
        String cmd = Common.JSON_GetFieldValue(aPackData, "cmd");
        //登录回复
        if (cmd.equals("LoginResponse"))
        {
            Log("Client登录成功");
        }
        //心跳
        if (cmd.equals("Timer"))
        {
            aReturnData = "{\"cmd\":\"TimerResponse\"}";
        }

        return aReturnData;
    }


    public void SocketReadErrorCallBack()
    {
        SocketErrorEvent();
    }

    //返回当前时间,ms
    private long GetTickes()
    {
        return System.currentTimeMillis();
    }

    //返回收到的数据包中从index起始位置的count个字节
    public byte[] PeekBytesValue(byte[] bytes, int index, int count)
    {
        byte[] buffer = new byte[count];
        System.arraycopy(bytes, index, buffer, 0, count);
        return buffer;
    }

    //查看收到的数据包中从index起始位置的count个字节位的字符串值
    private String PeekStringValue(byte[] bytes, int index, int count)
    {
        byte[] buffer = new byte[count];
        int nullLen = 0;
        System.arraycopy(bytes, index, buffer, 0, count);
        for (int i = 0; i < count; i++)
        {
            if (buffer[i] == 0)
            {
                buffer[i] = 32;  //将字符串结束标志改为空格符
                nullLen++;
            }
        }
        if (nullLen == count)
            return "";
        else
        {
            try
            {
                String strRtn = new String(buffer, "UTF-8");
                return strRtn;
            }
            catch(Exception e)
            {
                return "";
            }
        }
    }

    private byte[] GetCommanBuffer(String BodyData)
    {
        byte[] BodyByte = new byte[0];
        if (BodyData.length() > 0)
        {
            try
            {
                BodyByte = BodyData.getBytes("UTF-8");
            }
            catch(Exception e)
            {}
        }
        byte[] bytes = new byte[BodyByte.length + 4];
        int aIndex = 0;
        //长度，4位
        int aLen = BodyByte.length;
        byte[] buffer = intToByteArray(aLen);
        System.arraycopy(buffer, 0, bytes, aIndex, buffer.length);
        aIndex += 4;
        //消息体
        System.arraycopy(BodyByte, 0, bytes, aIndex, BodyByte.length);
        aIndex += BodyByte.length;

        buffer = null;
        return bytes;
    }

    private byte[] intToByteArray(int paramInt)
    {
        byte[] arrayOfByte = new byte[4];
        int i = 0;
        while (true)
        {
            if (i >= 4)
            {
                byte[] buffer = new byte[arrayOfByte.length];
                for (int n=0; n<buffer.length; n++)
                    buffer[n] = arrayOfByte[n];        //高位在前
                //buffer[n] = arrayOfByte[ buffer.length - n - 1];   //低位在前
                arrayOfByte = null;

                return buffer;
            }
            int j = (arrayOfByte.length - 1 - i) * 8;
            int k = (byte)(paramInt >>> j & 0xFF);
            arrayOfByte[i] = (byte)k;
            i += 1;
        }
    }

    private String DATA_10TO16(byte[] bytes)
    {
        char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        char[] buf = new char[bytes.length * 2];
        int a = 0;
        int index = 0;
        for(byte b : bytes) { // 使用除与取余进行转换
            if(b < 0) {
                a = 256 + b;
            } else {
                a = b;
            }

            buf[index++] = HEX_CHAR[a / 16];
            buf[index++] = HEX_CHAR[a % 16];
        }

        return new String(buf).toUpperCase();
    }

    private void SendMessageToUI(String data)
    {
        if (UIHandle != null)
        {
            try
            {
                Message msg=new Message();
                msg.what = 48;    //MsgID_SocketData
                msg.obj=data;
                UIHandle.sendMessage(msg);
            }
            catch(Exception ex)
            {}
        }
    }

    private void SendStatusToUI()
    {
        if (UIHandle != null)
        {
            try
            {
                String data = "" + ac.net_work_status;
                Message msg=new Message();
                msg.what = 50;    //MsgID_NetWorkStatus
                msg.obj = data;
                UIHandle.sendMessage(msg);
            }
            catch(Exception ex)
            {}
        }
    }

    public void SetHandle(Handler aH)
    {
        UIHandle = aH;
    }



    private byte[] GetP2PBuffer(String JsonData)
    {
        byte[] BodyByte = new byte[0];
        if (JsonData.length() > 0)
        {
            try
            {
                BodyByte = JsonData.getBytes("UTF-8");
            }
            catch(Exception e)
            {}
        }
        byte[] bytes = new byte[BodyByte.length + 12];
        int aIndex = 0;
        //tag，4位
        int tag = 0xAB000001;
        byte[] buffer = intToByteArray(tag);
        System.arraycopy(buffer, 0, bytes, aIndex, buffer.length);
        aIndex += 4;
        //type，4位
        int type = 0x01;
        buffer = intToByteArray(type);
        System.arraycopy(buffer, 0, bytes, aIndex, buffer.length);
        aIndex += 4;
        //size，4位
        int size = BodyByte.length;
        buffer = intToByteArray(size);
        System.arraycopy(buffer, 0, bytes, aIndex, buffer.length);
        aIndex += 4;
        //消息体
        System.arraycopy(BodyByte, 0, bytes, aIndex, BodyByte.length);
        aIndex += BodyByte.length;

        buffer = null;
        return bytes;
    }

}